﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace YinfangWeb.Common
{
    public class SecurityHelper
    {
        public static string ToBase64String(string encryptString)
        {
            byte[] enBytes = Encoding.UTF8.GetBytes(encryptString);
            string base64 = Convert.ToBase64String(enBytes);
            return base64;
        }

        public static string FromBase64String(string decryptString)
        {
            byte[] deBytes = Convert.FromBase64String(decryptString);
            string deString = Encoding.UTF8.GetString(deBytes);
            return deString;
        }

        public static string DESKey
        {
            get;
            set;
        }

        public static string BuildDESKey(string prevKey)
        {
            return (prevKey + DESKey).Substring(0, 8);
        }

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <param name="encryptKey"></param>
        /// <returns></returns>
        public static string EncryptDES(string encryptString, string encryptKey)
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(encryptString);
            byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey);
            byte[] encryptBytes = EncryptByDES(inputBytes, keyBytes, keyBytes);
            //string result =Encoding.UTF8.GetString(encryptBytes); //无法解码,其加密结果中文出现乱码：d\"?e????(??uπ?W??-??,_?\nJn7 
            //原因：如果明文为中文，UTF8编码两个字节标识一个中文字符，但是加密后，两个字节密文，不一定还是中文字符。
            using (DES des = new DESCryptoServiceProvider())
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        using (StreamWriter writer = new StreamWriter(cs))
                        {
                            writer.Write(inputBytes);
                        }
                    }
                }
            }
            string result = Convert.ToBase64String(encryptBytes);
            return result;
        }

        public static byte[] EncryptByDES(byte[] inputBytes, byte[] key, byte[] IV)
        {
            DES des = new DESCryptoServiceProvider
            {
                //建立加密对象的密钥和偏移量
                Key = key,
                IV = IV
            };

            //1、如果通过CryptoStreamMode.Write方式进行加密，然后CryptoStreamMode.Read方式进行解密，解密成功。
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputBytes, 0, inputBytes.Length);
                }
                return ms.ToArray();
            }
        }

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <returns></returns>
        public static string EncryptDES(string encryptString)
        {
            return EncryptDES(encryptString, DESKey);
        }


        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptString"></param>
        /// <param name="decryptKey"></param>
        /// <returns></returns>
        public static string DecryptDES(string decryptString, string decryptKey)
        {
            if (string.IsNullOrEmpty(decryptString)) return string.Empty;
            //UTF8无法解密，Error:要解密的数据的长度无效。
            //byte[] inputBytes =Encoding.UTF8.GetBytes(input);//UTF8乱码，见加密算法
            byte[] inputBytes = Convert.FromBase64String(decryptString);
            byte[] keyBytes = ASCIIEncoding.UTF8.GetBytes(decryptKey);
            byte[] resultBytes = DecryptByDES(inputBytes, keyBytes, keyBytes);
            string result = Encoding.UTF8.GetString(resultBytes);
            return result;
        }

        public static byte[] DecryptByDES(byte[] inputBytes, byte[] key, byte[] iv)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider
            {
                //建立加密对象的密钥和偏移量，此值重要，不能修改
                Key = key,
                IV = iv
            };

            //通过read方式解密
            using (MemoryStream ms = new MemoryStream(inputBytes))
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    using (StreamReader reader = new StreamReader(cs))
                    {
                        string result = reader.ReadToEnd();
                        return Encoding.UTF8.GetBytes(result);
                    }
                }
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptString"></param>
        /// <returns></returns>
        public static string DecryptDES(string decryptString)
        {
            return DecryptDES(decryptString, DESKey);
        }
        
        /// <summary>
        /// SHA-256加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <returns></returns>
        public static string Sha256Encrypt(string encryptString)
        {
            SHA256Managed sha256 = new SHA256Managed();
            UTF8Encoding utf8Encode = new UTF8Encoding();
            byte[] hashData = sha256.ComputeHash(utf8Encode.GetBytes(encryptString));
            sha256.Clear();
            return Convert.ToBase64String(hashData);
        }

        /// <summary>
        /// SHA-512加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <returns></returns>
        public static string Sha512Encrypt(string encryptString)
        {
            SHA512Managed sha512 = new SHA512Managed();
            UTF8Encoding utf8Encode = new UTF8Encoding();
            byte[] hashData = sha512.ComputeHash(utf8Encode.GetBytes(encryptString));
            sha512.Clear();
            return Convert.ToBase64String(hashData);
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="sourceStr"></param>
        /// <returns></returns>
        public static string MD5(string sourceStr)
        {
            string resultStr = "";

            byte[] b = Encoding.Default.GetBytes(sourceStr);
            b = new MD5CryptoServiceProvider().ComputeHash(b);
            for (int i = 0; i < b.Length; i++)
                resultStr += b[i].ToString("x").PadLeft(2, '0');

            return resultStr;
        }
    }
}
